package com.wuyan.web.auth.api;

import com.wuyan.helper.kit.RandomHelper;
import com.wuyan.helper.kit.verifycode.VerifyCodeSubject;
import com.wuyan.web.auth.entity.PubAccount;
import com.wuyan.web.auth.helper.email.EmailHelper;
import com.wuyan.web.auth.repo.PubAccountExtendRepo;
import com.wuyan.web.base.aop.ApiLogAnnotation;
import com.wuyan.web.base.helper.BaseApi;
import com.wuyan.web.base.helper.rep.RepBody;
import com.wuyan.web.base.helper.rep.RepCodeEnum;
import com.wuyan.web.base.helper.rep.RepHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

import static com.wuyan.helper.kit.VerifyCodeHelper.*;

/**
 * 验证码接口
 */

@Controller
@RequestMapping("api/verify")
public class VerifyCodeApi extends BaseApi implements RepHelper {

    @Autowired
    private PubAccountExtendRepo pubAccountExtendRepo;

    @Autowired
    private EmailHelper emailHelper;

    /**
     * 头部秘钥名称
     */
    public static final String HEADER_AUTH_KEY_NAME = "authorization-code";
    public static final String HEADER_AUTH_KEY_NAME2 = "Authorization-code";

    @Value("${wuyan.verify-code.len}")
    private int vcLen;

    @Value("${wuyan.verify-code.inLetter}")
    private boolean vcInLetter;

    @Value("${wuyan.verify-code.expires}")
    private int vcExpires;

    @Value("${wuyan.login.verify-code}")
    private boolean verifyCode;

    /**
     * 创建新的验证码信息，并返回二进制流
     *
     * @param request  请求体
     * @param response 响应体
     */
    @GetMapping("/code")
    @ApiLogAnnotation(name = "auth:verifyCode")
    public RepBody<Boolean> verifyCode(HttpServletRequest request, HttpServletResponse response) throws IOException {
        if (!verifyCode) {
            return error(RepCodeEnum.ERR_LOGIN_VERIFY_STOP);
        }

        //设置长宽
        VerifyCodeSubject verifyCode = generate(80, 28, vcLen, vcInLetter);
        String code = verifyCode.getCode();
        String ak = RandomHelper.createAccessToken();
        setAttr(request, ak, code, vcExpires);

        //设置响应头
        response.setHeader("Pragma", "no-cache");
        response.setHeader(HEADER_AUTH_KEY_NAME, ak);
        response.setHeader("Cache-Control", "no-cache");

        //在代理服务器端防止缓冲
        response.setDateHeader("Expires", 0);
        //设置响应内容类型
        response.setContentType(IMAGE_TYPE);
        response.getOutputStream().write(verifyCode.getImgBytes());
        response.getOutputStream().flush();

        return null;
    }

    /**
     * 将返回base64编码后的内容，常用于无法从header中取出授权信息的方式
     *
     * @param request  请求体
     * @param response 响应体
     */
    @GetMapping("/code-base64")
    @ResponseBody
    @ApiLogAnnotation(name = "auth:verifyCodeBase64")
    public RepBody<Map<String, Object>> verifyCodeBase64(HttpServletRequest request,
                                                         HttpServletResponse response) {
        if (!verifyCode) {
            return error(RepCodeEnum.ERR_LOGIN_VERIFY_STOP);
        }

        //设置长宽
        VerifyCodeSubject verifyCode = generate(80, 28, vcLen, vcInLetter);
        String code = verifyCode.getCode();
        String ak = RandomHelper.createAccessToken();
        setAttr(request, ak, code, vcExpires);

        byte[] codeImgBytes = verifyCode.getImgBytes();
        String encodeToString = Base64.getEncoder().encodeToString(codeImgBytes);

        response.setHeader(HEADER_AUTH_KEY_NAME, ak);

        Map<String, Object> data = new HashMap<>();
        data.put("code", "data:" + IMAGE_TYPE + ";base64," + encodeToString);
        data.put("secret", ak);
        data.put("expires", vcExpires);

        return ok(data);
    }

    /**
     * 发送注册验证码
     *
     * @param request  请求体
     * @param username 账户号
     * @return RepBody<String>
     */
    @GetMapping("/send-register/{username}")
    @ResponseBody
    @ApiLogAnnotation(name = "auth:register")
    public RepBody<String> register(HttpServletRequest request,
                                    @PathVariable(value = "username") String username) {
        VerifyCodeSubject verifyCode = generate(80, 28, vcLen, vcInLetter);
        String code = verifyCode.getCode().toUpperCase();
        String ak = RandomHelper.createAccessToken();
        setAttr(request, "register-" + ak, code, vcExpires);
        emailHelper.sendCodeMail("来自无言的验证码服务", code, username, vcExpires);
        return ok(ak);
    }

    /**
     * 发送重置密码服务的验证码
     *
     * @param request  请求体
     * @param username 账户号：手机号|邮箱
     * @return RepBody<String>
     */
    @GetMapping("/send-reset-pwd-code/{username}")
    @ResponseBody
    @ApiLogAnnotation(name = "auth:sendEmailCode")
    public RepBody<String> sendResetPwdCode(HttpServletRequest request,
                                            @PathVariable(value = "username") String username) {

        PubAccount pubAccount = pubAccountExtendRepo.findFirstByUsernameOrPhone(username, username);
        if (null == pubAccount) {
            return error(RepCodeEnum.ERR_LOGIN_USERNAME);
        }

        VerifyCodeSubject verifyCode = generate(80, 28, vcLen, vcInLetter);
        String code = verifyCode.getCode().toUpperCase();
        String ak = RandomHelper.createAccessToken();

        setAttr(request, "resetPwd-" + ak, code, vcExpires);

        emailHelper.sendCodeMail("来自无言的验证码服务", code, username, vcExpires);
        return ok(ak);
    }
}
